package imessage

import (
	"encoding/json"
	mux "github.com/julienschmidt/httprouter"
	"io"
	"log"
	"net/http"
	"strings"
	"time"
)

func render(v interface{}, w http.ResponseWriter) {
	if b, err := json.Marshal(v); err == nil {
		w.Write(b)
		return
	} else {
		log.Println(err)
	}
}

func internal_error(rw http.ResponseWriter, req *http.Request, _ interface{}) {
	rw.Header().Set("Server", "hls/0.1")
	http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}
func forbidden(rw http.ResponseWriter, req *http.Request) {
	rw.Header().Set("Server", "vdb/0.1")
	http.Error(rw, http.StatusText(http.StatusForbidden), http.StatusForbidden)
}

func badRequest(rw http.ResponseWriter, req *http.Request) {
	rw.Header().Set("Server", "vdb/0.1")
	http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
}
func is_multipart(r *http.Request) bool {
	ct := r.Header.Get("Content-Type")
	return (strings.HasPrefix(ct, "multipart") || strings.HasPrefix(ct, "Multipart")) && r.MultipartForm != nil
}

type Message struct {
	Sid         string    `json:"sid,-"`
	DeviceId    string    `json:"deviceId,-"`
	NodeId      string    `json:"nodeId,-"`
	MsgId       string    `json:"msgId,-"`
	Mtype       string    `json:"mtype,-"`
	From        string    `json:"from,-"`
	To          string    `json:"to,-"`
	Group       string    `json:"group,-"`
	Text        string    `json:"text,omitempty"`
	Attachs     []string  `json:"attachs,omitempty"`
	RecvTime    time.Time `json:"rtime,omitempty"`
	SentTime    time.Time `json:"stime,omitempty"`
	DeliverTime time.Time `json:"dtime,omitempty"`
	r           *http.Request
	w           http.ResponseWriter
	body        io.ReadCloser
}

/**
HTTP方法&URI：POST /im/member/login
URL参数：无
HEADER参数：
	X-Member:aaaaa 成员ID
	X-Key:fsadfasfsadfasfsaasf 登录令牌
	X-Device-Id:fdjalfjfadljsaf 设备ID
BODY参数：无

HTTP响应头
	X-Sid:7973491249242 会话ID
	X-Node:abcd
	X-Code:OK
**/
func (s *IMGatewayServer) on_member_login(w http.ResponseWriter, r *http.Request, _ mux.Params) {
	member := r.Header.Get("X-Member")
	token := r.Header.Get("X-Key")
	deviceId := r.Header.Get("X-Device-Id")
	if !user_auth(member, token) {
		w.Header().Add("X-Code", "Login Fail")
		return
	}
	loginTime := time.Now()

	if ss := s.router.FindSessionWithMember(member); ss != nil {
		ss.deviceId = deviceId
		ss.loginTime = loginTime
		ss.Active()
		w.Header().Add("x-sid", ss.sid)
		w.Header().Add("x-node", s.NodeId)
		w.Header().Add("x-code", "OK")
	} else {
		sid := UUID()
		session := &Session{member: member, sid: sid, lastActiveTime: loginTime, loginTime: loginTime, deviceId: deviceId, server: s}
		s.router.AddSession(session)
		w.Header().Add("x-sid", sid)
		w.Header().Add("x-node", s.NodeId)
		w.Header().Add("x-code", "OK")
	}

}

/**
HTTP方法&URI：POST /im/member/logout
URL参数：无
HEADER参数：
	X-Sid:7973491249242
BODY参数：无

HTTP响应头
	X-Code:OK
**/
func (s *IMGatewayServer) on_member_logout(w http.ResponseWriter, r *http.Request, _ mux.Params) {
	// if sid := r.Header.Get("x-sid"); sid == "" {
	// 	w.Header().Add("x-code", "SID REQUIRED")
	// 	w.WriteHeader()
	// 	return
	// } else {
	// 	s.router.RemoveSession(sid)
	// }
	w.Header().Add("x-code", "SID REQUIRED")
}

/**
HTTP方法&URI：POST /im/msg/send
URL参数：无
HEADER参数：
	X-Sid:7973491249242
	X-Msg-Id:fdsafsafsafdsa
	X-Type:IM|PUSH|HB
	X-From:fasf
	X-To/X-Group:fdasfsa //X-To和X-Group取其一，不能同时存在

BODY参数：Multipart
		form-type:text form-name:text
		form-type:file form-name:file

HTTP响应头:
	X-Recv-Time:2015-07-17 16:35:36
	X-Code:OK
**/
func (s *IMGatewayServer) on_send_msg(w http.ResponseWriter, r *http.Request, _ mux.Params) {
	sid := r.Header.Get("X-Sid")
	if sid == "" {
		w.Header().Add("x-code", "SID REQUIRED")
		return
	}
	msgid := r.Header.Get("X-Msg-Id")
	xtype := r.Header.Get("X-Type")
	//from := r.Header.Get("X-From")
	to := r.Header.Get("X-To")
	group := r.Header.Get("X-Group")

	if msgid == "" || xtype == "" || to == "" || group == "" {
		w.Header().Add("x-code", "PARAMETER ERROR")
		return
	}
	msg := &Message{}
	if ss := s.router.FindSessionWithSid(sid); ss == nil {
		w.Header().Add("x-code", "SESSION NOT FOUND")
		return
	} else {
		msg.DeviceId = ss.deviceId
		msg.From = ss.member
		msg.Group = group
		msg.To = to
		msg.Mtype = xtype
		msg.MsgId = msgid
		msg.Sid = sid
		msg.RecvTime = time.Now()
		msg.body = r.Body
		msg.r = r
		msg.w = w
	}

	if err := r.ParseMultipartForm(s.MaxMemory); err != nil {
		syslog.Println(err)
		w.Header().Add("x-code", "PARAMETER ERROR")
		return
	}

	if is_multipart(r) {
		//r.MultipartForm.Value["text"]
		//fhs := r.MultipartForm.File["file"]
		// for _, uf := range fhs {
		// 	filename := uf.Filename
		// 	file, err := uf.Open()
		// 	if err != nil {
		// 		w.Header().Add("x-code", "IO ERROR")
		// 		w.WriteHeader()
		// 		return
		// 	} else {
		// 		real_file := filepath.Join(root, file_path, filename)
		// 		if !exist(filepath.Dir(real_file)) {
		// 			os.MkdirAll(filepath.Dir(real_file), os.ModePerm)
		// 		}
		// 		f, err := os.OpenFile(real_file, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)
		// 		if err != nil {
		// 			log.Println(err)
		// 			w.Write([]byte(file_path + "/" + filename + " " + err.Error()))
		// 			w.Write([]byte("\r\n"))
		// 		} else {
		// 			defer f.Close()
		// 			io.Copy(f, file)
		// 			w.Write([]byte(file_path + "/" + filename + " OK"))
		// 			w.Write([]byte("\r\n"))
		// 		}
		// 	}
		// }
	} else {
		if err := json.NewDecoder(r.Body).Decode(msg); err != nil {
			syslog.Println(err)
			w.Header().Add("x-code", "PARAMETER ERROR")
			return
		} else {
			s.router.Forward(msg)
		}
	}
}
func (s *IMGatewayServer) on_forward_msg(w http.ResponseWriter, r *http.Request, _ mux.Params) {

}
func (s *IMGatewayServer) on_recv_msg(w http.ResponseWriter, r *http.Request, _ mux.Params) {
	sid := r.Header.Get("X-Sid")
	if sid == "" {
		w.Header().Add("x-code", "SID REQUIRED")
		return
	}
	ss := s.router.FindSessionWithSid(sid)
	if ss == nil {
		w.Header().Add("x-code", "SESSION NOT FOUND")
		//w.WriteHeader()
		return
	}
	hj, ok := w.(http.Hijacker)
	if !ok {
		internal_error(w, r, nil)
		return
	}
	conn, bufrw, err := hj.Hijack()
	if err != nil {
		internal_error(w, r, nil)
		syslog.Println(err)
		return
	}
	defer conn.Close()
	msg, more := <-ss.channel
	if !more {
		w.Header().Add("x-code", "OK")
		//w.WriteHeader()
		return
	}
	msg.SentTime = time.Now()
	b, err := json.Marshal(msg)
	if err != nil {
		w.Header().Add("x-code", "IO ERROR")
		//w.WriteHeader()
		return
	}
	w.Header().Add("X-Sid", sid)

	w.Header().Add("X-Msg-Id", msg.MsgId)
	w.Header().Add("X-Type", msg.Mtype)
	w.Header().Add("X-From", msg.From)
	if "" != msg.To {
		w.Header().Add("X-To", msg.To)
	}
	if "" != msg.Group {
		w.Header().Add("X-Group", msg.Group)
	}
	w.Header().Add("X-Send-Time", msg.SentTime.Format("2006-01-02 15:04:05"))
	_, err = bufrw.Write(b)
	if err == nil {
		err = bufrw.Flush()
	}
	if err != nil {
		syslog.Println(err)
		w.Header().Add("x-code", "IO ERROR")
		//w.WriteHeader()
		return
	}
}

func (s *IMGatewayServer) on_group_create(w http.ResponseWriter, r *http.Request, _ mux.Params) {

}

func (s *IMGatewayServer) on_group_remove(w http.ResponseWriter, r *http.Request, _ mux.Params) {

}

func (s *IMGatewayServer) on_group_join(w http.ResponseWriter, r *http.Request, _ mux.Params) {

}

func (s *IMGatewayServer) on_group_leave(w http.ResponseWriter, r *http.Request, _ mux.Params) {

}
